package com.shove.web.action;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;

import com.shove.Convert;
import com.shove.config.LianpayConfig;
import com.shove.util.FormUtil;
import com.shove.vo.LianpayInfo;
import com.shove.web.util.JSONUtils;
import com.sp2p.action.front.BaseFrontAction;
import com.sp2p.constants.IConstants;
import com.sp2p.entity.User;
import com.sp2p.service.HomeInfoSettingService;
import com.sp2p.service.RechargeService;
import com.sp2p.service.UserService;
import com.sp2p.util.DateUtil;
import com.llpay.client.conn.HttpRequestSimple;
import com.llpay.client.utils.LLPayUtil;
import com.llpay.client.vo.PayDataBean;
import com.llpay.client.vo.RetBean;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class LianPaymentAction extends BaseFrontAction {
	private static final long serialVersionUID = 1L;
	private static Log log = LogFactory.getLog(LianPaymentAction.class);

	private RechargeService rechargeService;
	private UserService userService;
	private HomeInfoSettingService homeInfoSettingService;

	public HomeInfoSettingService getHomeInfoSettingService() {
		return homeInfoSettingService;
	}

	public void setHomeInfoSettingService(
			HomeInfoSettingService homeInfoSettingService) {
		this.homeInfoSettingService = homeInfoSettingService;
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public RechargeService getRechargeService() {
		return rechargeService;
	}

	public void setRechargeService(RechargeService rechargeService) {
		this.rechargeService = rechargeService;
	}

	public String lianPayIsBindBankCard() throws Exception {
		User user = (User) session().getAttribute(IConstants.SESSION_USER);
		if (user == null) {
			return "noLogin";
		}

		String money = request("tranAmt");
		if (StringUtils.isBlank(money)) {
			return INPUT;
		}

		BigDecimal moneyDecimal;
		try {
			moneyDecimal = new BigDecimal(money);
		} catch (RuntimeException e) {
			return INPUT;
		}
		// 最小金额为0.01元
		int temp = moneyDecimal.compareTo(new BigDecimal("0.01"));
		if (temp < 0) {
			return INPUT;
		}
		request().setAttribute("tranAmt", money);

		List<Map<String, Object>> lists = homeInfoSettingService
				.querySuccessBankInfoList(user.getId());
		for (Map<String, Object> o : lists) {
			String isLianpayCard = o.get("isLianpayCard").toString();
			if (isLianpayCard.equals("1")) {
				request().setAttribute("lianpayBankCard", o);
				request().setAttribute("tranAmt", money);
				return "lianPaySubmit";
			}
		}

		// 实名信息
		Map<String, String> personMap = userService.queryPersonById(user
				.getId());
		String realName = Convert.strToStr(personMap.get("realName"), "");
		String idNo = Convert.strToStr(personMap.get("idNo"), "");
		if("".equals(realName)){
			return "bindBankCardAndIdNo";
		}else{
			request().setAttribute("realName", realName);
			request().setAttribute("idNo", idNo);
		}
		return "bindBankCard";

	}

	public void lianPayBindBankCard() throws Exception {
		JSONObject resObj = new JSONObject();
		User user = (User) session().getAttribute(IConstants.SESSION_USER);
		if (user == null) {
			resObj.put("msg", "noLogin");
			JSONUtils.printStr(resObj.toString());
			return;
		}

		String bankName = Convert.strToStr(paramMap.get("bankName"), null);
		String bankId = Convert.strToStr(paramMap.get("bankId"), null);
		String bankCard = Convert.strToStr(paramMap.get("bankCard"), null);

		// 查询银行卡bin信息
		String cardBin = queryCardBin(bankCard);
		JSONObject reqObj = JSON.parseObject(cardBin);
		if (reqObj.size() <= 0 || !reqObj.getString("ret_code").equals("0000")) {
			resObj.put("msg", "queryFail");
			JSONUtils.printStr(resObj.toString());
			System.out.println("===================>>>查询银行卡bin信息失败结果： "
					+ reqObj.getString("ret_msg"));
			return;
		} else {
			String bankCode = reqObj.getString("bank_code").toString();
			System.out.println("===================>>>bankId： " + bankId);
			System.out.println("===================>>>bankCode： "
					+ bankCode.substring(1, 4));
			if (!bankId.equals(bankCode.substring(1, 4))) {
				resObj.put("msg", "bankCodeError");
				JSONUtils.printStr(resObj.toString());
				return;
			}
		}

		// 查询快捷卡绑定情况
		Map<String, String> lianpayBankCardMap = homeInfoSettingService
				.queryLianpayBankCardInfo(user.getId());
		if (lianpayBankCardMap == null) {
			homeInfoSettingService.addLianpayBankCardInfo(user.getId(), user
					.getRealName(), bankName, bankId, bankName, bankCard, 3);
		} else {
			long bankCardId = Convert.strToLong(lianpayBankCardMap.get("id"),
					-1);
			homeInfoSettingService.modifyLianpayBankCardInfo(bankCardId,
					bankName, bankName, bankId, bankCard, 3);
		}

		resObj.put("msg", "success");
		JSONUtils.printStr(resObj.toString());

	}

	public String lianPayment() throws Exception {
		User user = (User) session().getAttribute(IConstants.SESSION_USER);
		if (user == null) {
			return "noLogin";
		}

		String bankCardno = request("bankCardNumber");
		String money = request("tranAmt");
		if (StringUtils.isBlank(money)) {
			return INPUT;
		}

		BigDecimal moneyDecimal;
		try {
			moneyDecimal = new BigDecimal(money);
		} catch (RuntimeException e) {
			return INPUT;
		}
		// 最小金额为0.01元
		int temp = moneyDecimal.compareTo(new BigDecimal("0.01"));
		if (temp < 0) {
			return INPUT;
		}

		long userId = this.getUserId();
		paramMap.put("rechargeMoney", moneyDecimal + "");
		paramMap.put("userId", userId + "");
		paramMap.put("result", "0");
		paramMap.put("addTime", DateUtil.dateToString(new Date()));

		// 添加充值明细;21：连连wap认证支付
		Map<String, String> result = rechargeService.addRecharge(paramMap, 21);
		long nunber = Convert.strToInt(result.get("result"), -1);

		// 实名信息
		Map<String, String> personMap = userService.queryPersonById(user
				.getId());
		String realName = personMap.get("realName");
		String idNo = personMap.get("idNo");
//		String realName = request("realName");
//		String idNo = request("idNo");

		if (nunber != -1) {
			String html = createLianpayUrl(result.get("result") + "", "在线充值",
					userId + "", moneyDecimal, userId, realName, idNo,
					bankCardno);
			sendHtml(html);
		} else {
			return INPUT; // 支付失败
		}

		return null;
	}

	private String createLianpayUrl(String out_trade_no, String body,
			String extraCommonParam, BigDecimal money, long userId,
			String realName, String idNo, String bankCardno) throws Exception {
		log.info("===================>>>调用 连连支付，认证支付充值接口start!!!");
		log.info("===================>>>商户订单号  " + out_trade_no);

		String orderDatetime = LLPayUtil.getCurrentDateTimeStr();// 商户订单提交时间

		LianpayInfo payInfo = new LianpayInfo();
		payInfo.setApp_request("3");// 请求应用标识 1-Android 2-ios 3-WAP
		payInfo.setBusi_partner(LianpayConfig.BUSI_PARTNER); // 商户业务类型
																// （101001：虚拟商品销售、109001：实物商品销售、108001：外部账户充值
		payInfo.setDt_order(orderDatetime);// 商户订单时间 （格式：YYYYMMDDH24MISS）
		payInfo.setInfo_order("共富网账户充值");// 订单描述
		payInfo.setMoney_order(money + "");// 交易金额（单位为RMB-元）
		payInfo.setName_goods("共富网账户充值");// 商品名称
		payInfo.setNo_order(out_trade_no);// 商户唯一订单号 （不重复的单号）
		payInfo.setNotify_url(LianpayConfig.NOTIFY_URL);// 服务器异步通知地址
		payInfo.setOid_partner(LianpayConfig.OID_PARTNER);// 商户号
		payInfo.setAcct_name(realName); // 姓名
		payInfo.setCard_no(bankCardno);// 卡号
		payInfo.setId_no(idNo);// 身份证号
		payInfo.setNo_agree("");// 协议号
		payInfo.setRisk_item(createRiskItem(userId, realName, idNo)); // 风控参数
		payInfo.setSign_type(LianpayConfig.SIGN_TYPE);// 签名方式（RSA或MD5）
		payInfo.setUrl_return(LianpayConfig.URL_RETURN);// 支付结束回显url
		payInfo.setUser_id(userId + "");// 商户用户唯一编号
		payInfo.setValid_order("10080");// 订单有效时间,分钟为单位，默认为10080分钟（7天）
		payInfo.setBg_color("128de4"); // 色值

		// 加签名
		String sign = LLPayUtil.addSign(JSON.parseObject(JSON
				.toJSONString(payInfo)), LianpayConfig.TRADER_PRI_KEY,
				LianpayConfig.MD5_KEY);

		payInfo.setSign(sign);
		String req_data = JSON.toJSONString(payInfo);

		log.info("===================>>>商户订单金额" + money);
		log.info("===================>>>签名类型 " + LianpayConfig.SIGN_TYPE);
		log.info("===================>>>商户号 " + LianpayConfig.OID_PARTNER);
		log.info("===================>>>订单提交时间 " + orderDatetime);

		Map<String, String> sParaTemp = new HashMap<String, String>();
		sParaTemp.put("req_data", req_data);

		log.info("===================>>>调用充值接口 	end!!!");
		log.info("===================>>>LIANPAY_GATEWAY:  " + LianpayConfig.LIANPAY_GATEWAY);
		return FormUtil.buildHtmlForm(sParaTemp, LianpayConfig.LIANPAY_GATEWAY,
				"post");
	}

	/**
	 * 通知商户网站支付结果
	 * 
	 * @return
	 * @throws Exception
	 */
	public String returnUrlLianpay() throws Exception {
		log.info("===================>>>连连支付回调函数returnUrlLianpay() Start!!!");
		log.info("===================>>>获取返回值");

		request().setCharacterEncoding("UTF-8");
		String reqStr = request().getParameter("res_data");

		log.info("===================>>>resData" + reqStr);

		JSONObject reqObj = JSON.parseObject(reqStr);
		if (reqObj == null) {
			return "failed"; // 支付失败
		}

		String oidPartner = reqObj.getString("oid_partner ");// 商户编号
		String dtOrder = reqObj.getString("dt_order");// 商户订单时间
		String noOrder = reqObj.getString("no_order");// 商户唯一订单号
		String oidPaybill = reqObj.getString("oid_paybill");// 连连支付支付单号
		String moneyOrder = reqObj.getString("money_order");// 交易金额
															// 该笔订单的资金总额，单位为
															// RMB-元。大于 0
															// 的数字，精确到小数点后两位。
		String resultPay = reqObj.getString("result_pay");// 支付结果 （SUCCESS 成功;
															// PROCESSING 处理中;
															// FAILURE 失败）
		String settleDate = reqObj.getString("settle_date");// 清算日期
		String signType = reqObj.getString("sign_type"); // 签名方式 RSA 或者 MD5
		String sign = reqObj.getString("sign"); // 签名

		log.info("===================>>>dt_order：" + dtOrder);
		log.info("===================>>>money_order：" + moneyOrder);
		log.info("===================>>>result_pay：" + resultPay);

		// 验证签名准确性
		// boolean verifyResult = LLPayUtil.checkSign(reqStr,
		// LianpayConfig.TRADER_PRI_KEY, LianpayConfig.MD5_KEY); //
		// 验证签名：返回true代表验签成功；否则验签失败

		// 验签成功，还需要判断订单状态
		// boolean paySuccess = verifyResult && resultPay.equals("SUCCESS");
		if (!resultPay.equals("SUCCESS")) {
			return "failed"; // 支付失败
		}
		log.info("===================>>>连连支付回调函数returnUrlLianpay() Start!!!");
		return SUCCESS;
	}

	public void notifyUrlLianpay() throws Exception {
		log.info("===================>>>进入连连支付异步通知数据接收处理 notifyUrlLianpay ()begin");
		response().setCharacterEncoding("UTF-8");
		RetBean retBean = new RetBean();
		String reqStr = LLPayUtil.readReqStr(request());
		if (LLPayUtil.isnull(reqStr)) {
			retBean.setRet_code("9999");
			retBean.setRet_msg("交易失败");
			response().getWriter().write(JSON.toJSONString(retBean));
			response().getWriter().flush();
			return;
		}
		log.info("===================>>>接收支付异步通知数据：【" + reqStr + "】");
		try {
			if (!LLPayUtil.checkSign(reqStr, LianpayConfig.YT_PUB_KEY,
					LianpayConfig.MD5_KEY)) {
				retBean.setRet_code("9999");
				retBean.setRet_msg("交易失败");
				response().getWriter().write(JSON.toJSONString(retBean));
				response().getWriter().flush();
				log.info("===================>>>支付异步通知验签失败");
				return;
			}
		} catch (Exception e) {
			log.info("===================>>>异步通知报文解析异常：" + e);
			retBean.setRet_code("9999");
			retBean.setRet_msg("交易失败");
			response().getWriter().write(JSON.toJSONString(retBean));
			response().getWriter().flush();
			return;
		}

		// 解析异步通知对象
		PayDataBean payDataBean = JSON.parseObject(reqStr, PayDataBean.class);

		// 平台账号充值
		double money = Convert.strToDouble(payDataBean.getMoney_order(), 0);
		String in_paynumber = payDataBean.getNo_order();
		Long rechargeId = Convert.strToLong(in_paynumber, 0);
		Map<String, String> rechargeMap = rechargeService
				.getRechargeDetail(rechargeId);
		long userId = Convert.strToLong(rechargeMap.get("userId"), -1);

		if (rechargeId > 0) {
			String remarks = "连连支付充值成功，充值金额：￥" + money;
			Map<String, String> resultMap = rechargeService.addUseraddmoney(
					userId, money, in_paynumber, remarks);
			String result = resultMap.get("result");
			log.info("===================>>>平台账号充值，result：" + result);
			retBean.setRet_code("0000");
			retBean.setRet_msg("交易成功");
			response().getWriter().write(JSON.toJSONString(retBean));
			response().getWriter().flush();
		} else {
			log.info("===================>>>平台账号充值失败，充值明细编号异常rechargeId："
					+ rechargeId);
			retBean.setRet_code("9999");
			retBean.setRet_msg("交易失败");
			response().getWriter().write(JSON.toJSONString(retBean));
			response().getWriter().flush();
			return;
		}
		log.info("===================>>>连连支付异步通知数据接收处理完成 notifyUrlLianpay() end!!!");

		// 绑定快捷卡
		bindBankCard(userId);

	}

	private void bindBankCard(long userId) throws Exception {
		Map<String, String> lianpayBankCardMap = homeInfoSettingService
				.queryLianpayBankCardInfo(userId);
		if (lianpayBankCardMap == null) {
			return;
		}
		int cardStatus = Convert.strToInt(lianpayBankCardMap.get("cardStatus"),
				-1);
		long bankCardId = Convert.strToLong(lianpayBankCardMap.get("id"), -1L);

		if (cardStatus == 3) {
			Long result = homeInfoSettingService
					.updateLianpayBankCardStatus(bankCardId);
			if (result > 0) {
				homeInfoSettingService.unboundBankCardExceptLianpay(userId);
			}
		}
	}

	private void realNameAuthen(long userId,String realName,String idNo) throws Exception {
		Map<String, String> personMap = userService.queryPersonById(userId);
		String rN = Convert.strToStr(personMap.get("realName"), "");
		if("".equals(rN)){
			userService.updateUserMater(userId);
			//userManageService.updateUser(userId, realName,idNo);
		}
	}

	public static String getProPath() {
		int port = ServletActionContext.getRequest().getServerPort();
		String portStr = "";
		if (port != 80) {
			portStr = ":" + port;
		}
		String path = ServletActionContext.getRequest().getScheme() + "://"
				+ ServletActionContext.getRequest().getServerName() + portStr
				+ ServletActionContext.getRequest().getContextPath() + "/";
		return path;
	}

	/**
	 * 根据连连支付风控部门要求的参数进行构造风控参数
	 * 
	 * @return
	 */
	private String createRiskItem(long userId, String realName, String idNo)
			throws Exception {
		Map<String, String> userMap = userService.queryUserById(userId);
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		Date date = df.parse(userMap.get("createTime"));
		String createTime = sdf.format(date);// 注册时间

		JSONObject riskItemObj = new JSONObject();
		riskItemObj.put("frms_ware_category", "2009"); // 商品类目 2009 P2P小额贷款
		riskItemObj.put("user_info_mercht_userno", userId + ""); // 商户用户唯一标识
		riskItemObj.put("user_info_dt_register", createTime); // 注册时间
		riskItemObj.put("user_info_full_name", realName); // 用户注册姓名
		riskItemObj.put("user_info_id_no", idNo); // 用户注册证件号码
		riskItemObj.put("user_info_identify_type", "1"); // 是否实名认证 1：:是 0：无认证
															// 商户自身是否对用户信息进行实名认证。默认：0
		riskItemObj.put("user_info_identify_ state", "4"); // 实名认证方式 是实名认证时，必填
															// 1：银行卡认证 2：现场认证
															// 3：身份证远程认证 4：其它认证
		return riskItemObj.toString();
	}

	/**
	 * 银行卡卡bin信息查询
	 * 
	 * @param req
	 * @return
	 */
	private String queryCardBin(String cardNo) {
		JSONObject reqObj = new JSONObject();
		reqObj.put("oid_partner", LianpayConfig.OID_PARTNER);
		reqObj.put("card_no", cardNo);
		reqObj.put("sign_type", LianpayConfig.SIGN_TYPE);
		String sign = LLPayUtil.addSign(reqObj, LianpayConfig.TRADER_PRI_KEY,
				LianpayConfig.MD5_KEY);
		reqObj.put("sign", sign);
		System.out.println("===================>>>sign： " + sign);
		String reqJSON = reqObj.toString();
		String resJSON = HttpRequestSimple.getInstance().postSendHttp(
				LianpayConfig.QUERY_BANKCARD_URL, reqJSON);
		return resJSON;
	}

}
